package biz.datalk.industrialland.admin.config;


import biz.datalk.industrialland.common.component.filter.DatalkCorsFilter;
import biz.datalk.industrialland.common.component.filter.DatalkCorsProperties;
import biz.datalk.industrialland.common.component.filter.MDCFilter;
import biz.datalk.industrialland.common.component.filter.RequestBodyReaderFilter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.HashMap;
import java.util.Map;

/**
 * 初始化 filter
 *
 * @author tarofang@163.com
 * @date 2019-09-15
 */
@Slf4j
@Configuration
public class FilterConfig {


    // /**/*.js,/**/*.css,/**/*.png,/**/*.jpeg,/**/*.jpg,/**/*.svg,/**/*.ico,/**/*.gif,/**/*.map,/**/*.swf,/**/*.eot,/**/*.woff,/**/*.ttf,/**/*.woff2,/**/*.less
    @Value("${datalk.core.filter.request-body-reader-filter.exclusions: /**/*.js,/**/*.css,/**/*.png,/**/*.jpeg,/**/*.jpg,/**/*.svg,/**/*.ico,/**/*.gif,/**/*.map,/**/*.swf,/**/*.eot,/**/*.woff,/**/*.ttf,/**/*.woff2,/**/*.less}")
    private String excludePatterns;

    @Autowired
    private DatalkCorsProperties datalkCorsProperties;

    @Bean("requestBodyReaderFilter")
    @ConditionalOnProperty(name = "datalk.core.filter.request-body-reader-filter.enable", havingValue = "true", matchIfMissing = true)
    public FilterRegistrationBean<RequestBodyReaderFilter> requestBodyReaderFilter() {
        FilterRegistrationBean<RequestBodyReaderFilter> registration = new FilterRegistrationBean<>();
        registration.setFilter(new RequestBodyReaderFilter());
        registration.addUrlPatterns("/*");
        registration.setName("requestBodyReaderFilter");
        registration.setOrder(Ordered.HIGHEST_PRECEDENCE + 1000);
        registration.setEnabled(Boolean.TRUE);

        Map<String, String> initParameters = new HashMap<>(4);
        initParameters.put("excludePatterns", excludePatterns.replaceAll("\\s", ""));
        registration.setInitParameters(initParameters);

        return registration;
    }

    @Bean("datalkCorsFilter")
    @ConditionalOnProperty(name = "datalk.cors.enable", havingValue = "true", matchIfMissing = true)
    public FilterRegistrationBean<DatalkCorsFilter> datalkCorsFilter() {
        log.debug("init datalkCorsFilter ===========> start");
        try {
            final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
            final CorsConfiguration corsConfiguration = new CorsConfiguration();
            /* 是否允许请求带有验证信息 */
            corsConfiguration.setAllowCredentials(datalkCorsProperties.getAllowCredentials());
            /* 允许访问的客户端域名 */
            for (String origin : datalkCorsProperties.getAccessControlAllowOrigin()) {
                corsConfiguration.addAllowedOrigin(origin);
            }
            /* 允许服务端访问的客户端请求头 */
            for (String header : datalkCorsProperties.getAccessControlAllowHeaders()) {
                corsConfiguration.addAllowedHeader(header);
            }
            /* 允许访问的方法名,GET POST等 */
            for (String method : datalkCorsProperties.getAccessControlAllowMethods()) {
                corsConfiguration.addAllowedMethod(method);
            }
            urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
            DatalkCorsFilter datalkCorsFilter = new DatalkCorsFilter(urlBasedCorsConfigurationSource);

            FilterRegistrationBean<DatalkCorsFilter> registration = new FilterRegistrationBean<>();
            registration.setFilter(datalkCorsFilter);
            registration.addUrlPatterns("/*");
            registration.setName("datalkCorsFilter");
            registration.setOrder(Ordered.HIGHEST_PRECEDENCE + 10);
            registration.setEnabled(Boolean.TRUE);

            return registration;
        } finally {
            log.debug("init datalkCorsFilter ===========> finish");
        }
    }

    @Bean("mdcFilter")
    @ConditionalOnProperty(name = "datalk.logmdc.enable", havingValue = "true", matchIfMissing = true)
    public FilterRegistrationBean<MDCFilter> mdcFilter() {

        log.debug("init mdcFilter ===========> start");
        try {

            FilterRegistrationBean<MDCFilter> registration = new FilterRegistrationBean<>();
            registration.setFilter(new MDCFilter());
            registration.addUrlPatterns("/*");
            registration.setName("mdcFilter");
            registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
            registration.setEnabled(Boolean.TRUE);

            return registration;
        } finally {
            log.debug("init mdcFilter ===========> finish");
        }
    }
}
